import javax.swing.*;
import java.awt.*;   
import java.awt.event.*;        
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;


public class AssemblerFrame extends JPanel implements ActionListener {
	JButton openButton, saveButton, actionButton, clearButton;
	JTextField openDirectory, saveDirectory;
	static JTextArea inputTextArea, outputTextArea, symbolTextArea, lfileArea;
	static JFileChooser fcOpen, fcSave;
	static boolean batch;
	int errorcounter;
	
	private final String newline = System.getProperty("line.separator");
    public static String separator = System.getProperty("file.separator");
	
	public AssemblerFrame(){
		super(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.insets = new Insets(10,10,10,10);
		
		//File Choosers
		fcOpen = new JFileChooser();
		fcOpen.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
		fcSave = new JFileChooser();
		fcSave.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		
		//TOP
		JLabel title = new JLabel("CSE 560 Group 02 - Linker/Loader");
        title.setFont(new Font(null, Font.BOLD, 25));
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 3;
		super.add(title,c);
		
		clearButton = new JButton("Clear");
		clearButton.addActionListener(this);
		clearButton.setEnabled(true);
		c.gridy = 7;
		c.gridx = 3;
		c.gridwidth = 1;
		super.add(clearButton,c);
		actionButton = new JButton("Link/Load");
		actionButton.addActionListener(this);
		actionButton.setEnabled(false);
		c.gridy = 7;
		c.gridx = 0;
		c.gridwidth = 1;
		super.add(actionButton,c);
		
		//MIDDLE
		openButton = new JButton("Open...");
		openButton.setToolTipText("Choose input file to link and load");
		openButton.addActionListener(this);
		openDirectory = new JTextField();
		openDirectory.setEditable(false);
		
		saveButton = new JButton("Save...");
		saveButton.setToolTipText("Choose directory to save output files");
		saveButton.addActionListener(this);
		saveButton.setEnabled(false);
		saveDirectory = new JTextField();
		saveDirectory.setEditable(false);
		
        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.CENTER;
	    c.fill = GridBagConstraints.NONE;
	    super.add(openButton, c);
	    c.gridy = 3;
	    super.add(saveButton, c);
	    
        c.gridx = 1;
        c.gridy = 2;
        c.gridwidth = 3;
        c.weightx = 1.0;
	    c.fill = GridBagConstraints.HORIZONTAL;
	    super.add(openDirectory, c);
	    c.gridy = 3;
	    super.add(saveDirectory, c);


	    //BOTTOM
	    JTabbedPane console = new JTabbedPane();
	    inputTextArea = new JTextArea(5, 20);
	    inputTextArea.setEditable(false);
	    outputTextArea = new JTextArea(5, 20);
	    outputTextArea.setEditable(false);
	    symbolTextArea = new JTextArea(5, 20);
	    symbolTextArea.setEditable(false);
	    lfileArea = new JTextArea(5, 20);
	    lfileArea.setEditable(false);
	    
	    JScrollPane inputScrollPane = new JScrollPane(inputTextArea);
	    JScrollPane outputScrollPane = new JScrollPane(outputTextArea);
	    JScrollPane symbolScrollPane = new JScrollPane(symbolTextArea);
	    JScrollPane lfileScrollPane = new JScrollPane(lfileArea);
	    
	    console.addTab("Input", inputScrollPane);
	    console.addTab("Output", outputScrollPane);
	    console.addTab("Symbol Table", symbolScrollPane);
	    console.addTab("Load File", lfileScrollPane);
	    
        c.gridx = 0;
        c.gridy = 8;
        c.gridwidth = 4;
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.anchor = GridBagConstraints.NORTH;
        c.fill = GridBagConstraints.BOTH;
	    super.add(console,c);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//Handle open button action.
		if (e.getSource() == openButton) {
			int returnVal = fcOpen.showOpenDialog(AssemblerFrame.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				if(fcOpen.getSelectedFile().isDirectory()){
					openDirectory.setText(fcOpen.getSelectedFile().getAbsolutePath());
					if(saveButton.isEnabled()){
						saveDirectory.setText(fcSave.getSelectedFile().getPath() + separator);
					}
					saveButton.setEnabled(true);	
					batch = true;
				}else if(fcOpen.getSelectedFile().isFile()){
					openDirectory.setText(fcOpen.getSelectedFile().getAbsolutePath());
					if(saveButton.isEnabled()){
						saveDirectory.setText(fcSave.getSelectedFile().getPath() + separator);
					}
					saveButton.setEnabled(true);
					batch = false;
				}
			}
		}

		//Handle save button action.
		if (e.getSource() == saveButton) {
			int returnVal = fcSave.showOpenDialog(AssemblerFrame.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				if(fcOpen.getSelectedFile().isDirectory()){
					saveDirectory.setText(fcSave.getSelectedFile().getPath() + separator);
				}else if(fcOpen.getSelectedFile().isFile()){
					saveDirectory.setText(fcSave.getSelectedFile().getPath() + separator);
				}
				actionButton.setEnabled(true);
			} else {
			}
		}

		//Handle assemble button action.
		if (e.getSource() == actionButton) {
			inputTextArea.setText("");
			outputTextArea.setText("");
			symbolTextArea.setText("");
			lfileArea.setText("");
			
			if(batch){
				for(int x=0; x<fcOpen.getSelectedFile().listFiles().length; x++){
					if(fcOpen.getSelectedFile().listFiles()[x].isFile() && fcOpen.getSelectedFile().listFiles()[x].canRead()){
						if(!(fcOpen.getSelectedFile().listFiles()[x].getName().endsWith("_OUTPUT.txt")||fcOpen.getSelectedFile().listFiles()[x].getName().endsWith("_PROGRAM_LENGTH.txt")||fcOpen.getSelectedFile().listFiles()[x].getName().endsWith("_SYMBOL.txt"))){
							//batchTextArea.append(fcOpen.getSelectedFile().listFiles()[x].getName() + ": ");
							Main.run(fcOpen.getSelectedFile().listFiles()[x]);
							//batchTextArea.append(Main.INTERMEDIATE_FILE.errorCount() + " Errors" + newline);
							
							saveBatchOutput(fcSave.getSelectedFile(), fcOpen.getSelectedFile().listFiles()[x]);
							
							inputTextArea.setText("");
							outputTextArea.setText("");
							symbolTextArea.setText("");
							lfileArea.setText("");
						}
					}
				}
			}else{
				Main.run(fcOpen.getSelectedFile());	
				saveOutput(fcSave.getSelectedFile());
			}
		}
		
		//Handle clear button action.
		if (e.getSource() == clearButton) {
			inputTextArea.setText("");
			outputTextArea.setText("");
			symbolTextArea.setText("");
			lfileArea.setText("");
		}
	}
	
	public static void saveBatchOutput(File output, File input){
		try{
			FileWriter outStream = new FileWriter(output.getPath() + separator + removeExtension(input.getName()) + "_SIMOUTPUT.txt");
			FileWriter tableStream = new FileWriter(output.getPath() + separator + removeExtension(input.getName()) + "_SIMTABLE.txt");
			FileWriter lfileStream = new FileWriter(output.getPath() + separator + removeExtension(input.getName()) + "_LFILE.txt");
			BufferedWriter out = new BufferedWriter(outStream);
			BufferedWriter tbl = new BufferedWriter(tableStream);
			BufferedWriter lfl = new BufferedWriter(lfileStream);
			out.write(outputTextArea.getText());
			tbl.write(symbolTextArea.getText());
			lfl.write(lfileArea.getText());
			out.close();
			tbl.close();
			lfl.close();
		}catch (Exception e){
			System.err.println("FILE WRITE ERROR");
		}
	}
	
	public static void saveOutput(File file){
		try{
			FileWriter outStream = new FileWriter(file.getPath() + separator + removeExtension(fcOpen.getSelectedFile().getName()) + "_SIMOUTPUT.txt");
			FileWriter tableStream = new FileWriter(file.getPath() + separator + removeExtension(fcOpen.getSelectedFile().getName()) + "_SIMTABLE.txt");
			FileWriter lfileStream = new FileWriter(file.getPath() + separator + removeExtension(fcOpen.getSelectedFile().getName()) + "_LFILE.txt");
			BufferedWriter out = new BufferedWriter(outStream);
			BufferedWriter tbl = new BufferedWriter(tableStream);
			BufferedWriter lfl = new BufferedWriter(lfileStream);
			out.write(outputTextArea.getText());
			tbl.write(symbolTextArea.getText());
			lfl.write(lfileArea.getText());
			out.close();
			tbl.close();
			lfl.close();
		}catch (Exception e){
			System.err.println("FILE WRITE ERROR");
		}
	}
	
	public static String removeExtension(String s) {
	    String filename;

	    int lastSeparatorIndex = s.lastIndexOf(separator);
	    
	    if (lastSeparatorIndex == -1) {
	        filename = s;
	    } else {
	        filename = s.substring(lastSeparatorIndex + 1);
	    }
	    
	    int extensionIndex = filename.lastIndexOf(".");
	    if (extensionIndex == -1){
	    	return filename;
	    }
	     
	    return filename.substring(0, extensionIndex);
	}
	
	public static JTextArea getInputArea(){
		return inputTextArea;
	}
	
	public static JTextArea getOutputArea(){
		return outputTextArea;
	}
	
	public static JTextArea getSymbolArea(){
		return symbolTextArea;
	}
	
	public static JTextArea getLfileArea(){
		return lfileArea;
	}
}
